package com.example.auth.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 自定义OAuth2异常转换器，用于处理TokenEndpoint抛出的异常
 */
@Component
@Slf4j
public class CustomOAuth2ExceptionTranslator implements WebResponseExceptionTranslator<OAuth2Exception> {

    private final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public ResponseEntity<OAuth2Exception> translate(Exception exception) throws Exception {
        log.info("开始自定义拦截异常 {}",new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        // 1. 首先检查是否是 InvalidGrantException，且原因是 BadCredentialsException
        if (exception instanceof InvalidGrantException) {
            Throwable cause = exception.getCause();
            if (cause instanceof BadCredentialsException) {
                return handleBadCredentials((InvalidGrantException) exception, (BadCredentialsException) cause);
            }
            return handleInvalidGrant((InvalidGrantException) exception);
        }

        // 2. 处理其他 OAuth2Exception
        if (exception instanceof OAuth2Exception) {
            return handleOAuth2Exception((OAuth2Exception) exception);
        }

        // 3. 处理其他未知异常
        return handleUnknownException(exception);
    }

    /**
     * 处理用户名密码错误的异常
     */
    private ResponseEntity<OAuth2Exception> handleBadCredentials(InvalidGrantException ex, BadCredentialsException cause) {
        Map<String, Object> response = createErrorResponse(
                HttpStatus.UNAUTHORIZED.value(),
                "认证失败",
                "用户名或密码错误", // 安全提示，不明确说是用户名还是密码错误
                1001,
                ex.getOAuth2ErrorCode()
        );
        OAuth2Exception auth2Exception=new OAuth2Exception(ex.getMessage());
        auth2Exception.addAdditionalInformation("code","1");

        return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(auth2Exception);
    }

    /**
     * 处理其他 InvalidGrantException
     */
    private ResponseEntity<OAuth2Exception> handleInvalidGrant(InvalidGrantException ex) {
        Map<String, Object> response = createErrorResponse(
                HttpStatus.BAD_REQUEST.value(),
                "授权失败",
                ex.getMessage(),
                1002,
                ex.getOAuth2ErrorCode()
        );
        OAuth2Exception auth2Exception=new OAuth2Exception(ex.getMessage());
        auth2Exception.addAdditionalInformation("code","1");

        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(auth2Exception);
    }

    /**
     * 处理其他 OAuth2Exception
     */
    private ResponseEntity<OAuth2Exception> handleOAuth2Exception(OAuth2Exception ex) {
        Map<String, Object> response = createErrorResponse(
                HttpStatus.BAD_REQUEST.value(),
                "OAuth2错误",
                ex.getMessage(),
                1003,
                ex.getOAuth2ErrorCode()
        );
        OAuth2Exception auth2Exception=new OAuth2Exception(ex.getMessage());
        auth2Exception.addAdditionalInformation("code","1");


        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(auth2Exception);
    }

    /**
     * 处理未知异常
     */
    private ResponseEntity<OAuth2Exception> handleUnknownException(Exception ex) {
        Map<String, Object> response = createErrorResponse(
                HttpStatus.INTERNAL_SERVER_ERROR.value(),
                "系统错误",
                "服务器内部错误，请稍后重试", // 生产环境不要返回详细错误信息
                5000,
                "server_error"
        );
        OAuth2Exception auth2Exception=new OAuth2Exception(ex.getMessage());
        auth2Exception.addAdditionalInformation("code","1");

        // 记录完整异常日志，便于排查
        ex.printStackTrace();

        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(auth2Exception);
    }

    /**
     * 创建统一的错误响应格式
     */
    private Map<String, Object> createErrorResponse(int status, String error, String message,
                                                    int code, String oauthErrorCode) {
        Map<String, Object> response = new LinkedHashMap<>();
        response.put("code", code);              // 自定义业务错误码
        response.put("status", status);          // HTTP状态码
        response.put("error", error);            // 错误类型
        response.put("message", message);        // 错误信息
        response.put("oauth_error", oauthErrorCode); // OAuth2原始错误码
        response.put("timestamp", System.currentTimeMillis());
        response.put("data", null);
        return response;
    }
}